﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Family.Core;
using Family.Core.Model;
using Family.Core.Exceptions;
using Family.Core.DataInterfaces;
using Family.Core.Model;
using Family.Data.DBRepositories;
using Family.Data.Factories;


public partial class Controls_OrdersControl : System.Web.UI.UserControl
{

    #region Private fields

    private const String CATEGORY_KEY = "CategoryKey";
    private const String SELECTED_CATEGORY_KEY = "SelectedCategoryKey";
    private const String PRODUCT_KEY = "ProductKey";
    private const String FILTER = "Filter";
    private const String SELECTED_PRODUCT_KEY = "SelectedProductKey";
    private const String ORDER_KEY = "OrderKey";
    private const String DATE_FORMAT = "dd-MM-yyyy";

    private IRepository<Category> cRepo;
    private IRepository<OrderItem> oiRepo;
    private ProductRepository pRepo;
    private OrderRepository oRepo;

    #endregion

    #region Private methods and properties

    private void BindCategories()
    {
        lvCategories.DataSource = cRepo.GetAll();
        lvCategories.DataBind();
    }

    private void BindProductsByCategoryId(Int32 id)
    {
        lvProducts.DataSource = id > 0 ? pRepo.GetProductsByCategoryId(id) : null;
        lvProducts.DataBind();
    }

    private void BindFilteredProductsByCategoryId(Int32 id, String mask)
    {
        var pp = pRepo.GetProductsByCategoryIdWithMask(id, mask) as List<Product>;
        Int32 index = pp.FindIndex(x => x.Id == CurrentProductID);

        lvProducts.SelectedIndex = index;
        lvProducts.DataSource = id > 0 ? pp : null;
        lvProducts.DataBind();
    }

    private void BindOrders(DateTime date)
    {
        var order = oRepo.GetOrderByDate(date);
        day.BindOrder(order);
    }

    private void EnableControls(Boolean isEnable)
    {
        txtAmount.Enabled = btnAdd.Enabled = isEnable;
    }

    private void BindDate(DateTime date)
    {
        lvCategories.SelectedIndex = -1;
        BindCategories();
        BindProductsByCategoryId(0);
        BindOrders(date);
        EnableControls(false);
        txtAmount.Text = String.Empty;
    }

    private Int32 CurrentCategoryID
    {
        get
        {
            return ViewState[CATEGORY_KEY] == null ? 0 : (Int32) ViewState[CATEGORY_KEY];
        }
        set { ViewState[CATEGORY_KEY] = value; }
    }

    private Int32 EditedCategoryID
    {
        get 
        {
            return ViewState[SELECTED_CATEGORY_KEY] == null ? 0 : (Int32)ViewState[SELECTED_CATEGORY_KEY];
        }
        set { ViewState[SELECTED_CATEGORY_KEY] = value; }
    }

    private Int32 CurrentProductID
    {
        get
        {
            return ViewState[PRODUCT_KEY] == null ? 0 : (Int32) ViewState[PRODUCT_KEY];
        }
        set { ViewState[PRODUCT_KEY] = value; }
    }

    private Int32 EditedProductID
    {
        get 
        {
            return ViewState[SELECTED_PRODUCT_KEY] == null ? 0 : (Int32)ViewState[SELECTED_PRODUCT_KEY];
        }
        set { ViewState[SELECTED_PRODUCT_KEY] = value; }
    }

    private String Mask
    {
        get
        {
            return ViewState[FILTER] == null ? String.Empty : ViewState[FILTER].ToString();
        }
        set { ViewState[FILTER] = value; }
    }

    #endregion

    #region Controls' events

    protected Controls_OrdersControl()
    {
        cRepo = new Repository<Category>(WebFactory.CurrentSession);
        oiRepo = new Repository<OrderItem>(WebFactory.CurrentSession);
        pRepo = new ProductRepository(WebFactory.CurrentSession);
        oRepo = new OrderRepository(WebFactory.CurrentSession);
    }
    
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //txtDate.Text = DateTime.Now.ToString(DATE_FORMAT);
            mainCalendar.SelectedDate = DateTime.Now;
            BindDate(DateTime.Today);

            var txt = lvProducts.FindControl("txtProductName") as TextBox;
            if (txt != null)
            {
                txt.Attributes.Add("onkeyup", String.Format("onKeyUp(event, '{0}');", txt.ClientID)); //Page.ClientScript.GetPostBackEventReference(txt, ""));
            }
        }
    }

    protected void lvCategories_ItemInserting(object sender, ListViewInsertEventArgs e)
    {
        Page.Validate("categoryInsert");
        if (Page.IsValid)
        {
            var txtName = lvCategories.InsertItem.FindControl("txtName") as TextBox;
            if (txtName != null)
            {
                var category = new Category();

                category.Name = txtName.Text;

                cRepo.SaveOrUpdate(category);
            }

            BindCategories();
        }
    }

    protected void lvCategories_SelectedIndexChanging(object sender, ListViewSelectEventArgs e)
    {
        CurrentCategoryID = (Int32) lvCategories.DataKeys[e.NewSelectedIndex].Value;
        lvProducts.SelectedIndex = -1;
        BindFilteredProductsByCategoryId(CurrentCategoryID, Mask);
        lvCategories.SelectedIndex = e.NewSelectedIndex;
        EnableControls(false);
        lblProductName.Text = String.Empty;
        BindCategories();
    }

    protected void lvProducts_ItemInserting(object sender, EventArgs e)
    {
        Page.Validate("productInsert");
        if (Page.IsValid)
        {
            if (CurrentCategoryID != 0)
            {
                var txtName = lvProducts.InsertItem.FindControl("txtName") as TextBox;
                if (txtName != null)
                {
                    var product = new Product(cRepo.Get(CurrentCategoryID));

                    product.Name = txtName.Text;

                    pRepo.SaveOrUpdate(product);
                }
                BindProductsByCategoryId(CurrentCategoryID);
            }
        }
    }

    protected void lvProducts_SelectedIndexChanging(object sender, ListViewSelectEventArgs e)
    {
        var txt = lvProducts.FindControl("txtProductName") as TextBox;
        
        CurrentProductID = (Int32)lvProducts.DataKeys[e.NewSelectedIndex].Value;
        lvProducts.SelectedIndex = e.NewSelectedIndex;
        lblProductName.Text = String.Format(@"Выбран продукт - {0} !", pRepo.Get(CurrentProductID).Name);
        EnableControls(true);
        BindFilteredProductsByCategoryId(CurrentCategoryID, txt.Text);
    }

    //protected void txtDate_TextChanged(object sender, EventArgs e)
    //{
    //    DateTime date;
    //    if (DateTime.TryParse(txtDate.Text, out date))
    //    {
    //        BindDate(date);
    //    }
    //}

    protected void txtProductName_Changed(object sender, EventArgs e)
    {
        var txt = sender as TextBox;
        Mask = txt.Text;
        BindFilteredProductsByCategoryId(CurrentCategoryID, Mask);

        ScriptManager.RegisterStartupScript(txt, txt.GetType(), "SetCaret", String.Format("setCaret('{0}');", txt.ClientID), true);
    }

    protected void btnAdd_Click(object sender, EventArgs e)
    {
        var date = mainCalendar.SelectedDate; //DateTime.Parse(txtDate.Text);
        var order = oRepo.GetOrderByDate(date);
        if (order == null)
        {
            order = new Order {Date = date};
            oRepo.SaveOrUpdate(order);
        }
        var product = pRepo.Get(CurrentProductID);
        var oi = new OrderItem(order, product) {Amount = Decimal.Parse(txtAmount.Text)};
        oiRepo.SaveOrUpdate(oi);

        lvProducts.SelectedIndex = -1;
        txtAmount.Text = String.Empty;
        EnableControls(false);

        BindOrders(date);
    }

    protected void lvCategories_ItemDataBound(object sender, ListViewItemEventArgs e)
    {
        if (e.Item.ItemType == ListViewItemType.DataItem)
        {
            var lnk = e.Item.FindControl("btnSelect") as ImageButton;
            var tr = e.Item.FindControl("tr") as HtmlTableRow;
            if (lnk != null && tr != null)
            {
                tr.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(lnk, e.Item.DataItemIndex.ToString());
            }
        }
    }

    protected void lvProducts_ItemDataBound(object sender, ListViewItemEventArgs e)
    {
        if (e.Item.ItemType == ListViewItemType.DataItem)
        {
            var lnk = e.Item.FindControl("btnSelect") as ImageButton;
            var tr = e.Item.FindControl("tr") as HtmlTableRow;
            if (lnk != null && tr != null)
            {
                tr.Attributes["onclick"] = Page.ClientScript.GetPostBackClientHyperlink(lnk, e.Item.DataItemIndex.ToString());
            }
        }
    }

    protected void lvCategories_Canceling(object sender, ListViewCancelEventArgs e)
    {
        lvCategories.EditIndex = -1;
        BindCategories();
    }

    protected void lvCategories_Deleting(object sender, ListViewDeleteEventArgs e)
    {
        var key = (Int32) lvCategories.DataKeys[e.ItemIndex].Value;
        var entity = cRepo.Get(key);
        cRepo.Delete(entity);
        BindCategories();
    }

    protected void lvCategories_Editing(object sender, ListViewEditEventArgs e)
    {
        EditedCategoryID = (Int32) lvCategories.DataKeys[e.NewEditIndex].Value;
        lvCategories.EditIndex = e.NewEditIndex;
        BindCategories();
    }

    protected void lvCategories_Updating(object sender, ListViewUpdateEventArgs e)
    {
        var txt = lvCategories.Items[e.ItemIndex].FindControl("txtName") as TextBox;
        if (txt != null)
        {
            var c = cRepo.Get(EditedCategoryID);
            c.Name = txt.Text;
            cRepo.SaveOrUpdate(c);
            lvCategories.EditIndex = -1;
            BindCategories();
        }
    }

    protected void lvProducts_Canceling(object sender, ListViewCancelEventArgs e)
    {
        lvProducts.EditIndex = -1;
        BindProductsByCategoryId(CurrentCategoryID);
    }

    protected void lvProducts_Deleting(object sender, ListViewDeleteEventArgs e)
    {
        var key = (Int32) lvProducts.DataKeys[e.ItemIndex].Value;
        var entity = pRepo.Get(key);
        entity.Category.Products.Remove(entity);
        pRepo.Delete(entity);
        BindProductsByCategoryId(CurrentCategoryID);
    }

    protected void lvProducts_Editing(object sender, ListViewEditEventArgs e)
    {
        EditedProductID = (Int32)lvProducts.DataKeys[e.NewEditIndex].Value;
        lvProducts.EditIndex = e.NewEditIndex;
        BindProductsByCategoryId(CurrentCategoryID);
    }

    protected void lvProducts_Updating(object sender, ListViewUpdateEventArgs e)
    {
        var txt = lvProducts.Items[e.ItemIndex].FindControl("txtName") as TextBox;
        if (txt != null)
        {
            var p = pRepo.Get(EditedProductID);
            p.Name = txt.Text;
            pRepo.SaveOrUpdate(p);
            lvProducts.EditIndex = -1;
            BindProductsByCategoryId(CurrentCategoryID);
        }
    }

    protected void mainCalendar_DayRender(object sender, DayRenderEventArgs e)
    {
        var day = e.Cell.Controls[0];
        var amount = oRepo.GetAmountByDate(e.Day.Date);

        e.Cell.Controls.Clear();

        var tbl = new HtmlTable();
        tbl.Width = "100%";

        var row1 = new HtmlTableRow();
        var cell1 = new HtmlTableCell();
        cell1.Controls.Add(day);
        cell1.Attributes.Add("class", "dateRow");
        row1.Cells.Add(cell1);

        var row2 = new HtmlTableRow();
        var cell2 = new HtmlTableCell();
        cell2.Attributes.Add("class", "amountRow");
        cell2.Controls.Add(new Label { Text = amount.ToString("N2") });
        row2.Cells.Add(cell2);

        tbl.Rows.Add(row1);
        tbl.Rows.Add(row2);

        if (amount < 100)
        {
            tbl.BgColor = "GreenYellow";
        }
        else if (amount < 1000)
        {
            tbl.BgColor = "Yellow";
        }
        else
        {
            tbl.BgColor = "Red";
        }

        e.Cell.Controls.Add(tbl);
    }

    protected void mainCalendar_SelectionChanged(object sender, EventArgs e)
    {
        var c = sender as Calendar;
        if (c != null)
        {
            BindDate(c.SelectedDate);
        }
    }

    #endregion
}